package com.okoj.excel_lib_rary.ui;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.loader.content.CursorLoader;

import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.LogUtils;
import com.fenghuajueli.libbasecoreui.utils.BaseConfigFileProvider;
import com.forjrking.lubankt.Luban;
import com.forjrking.lubankt.ext.CompressResult;
import com.google.gson.JsonObject;
import com.okoj.excel_lib_rary.R;
import com.okoj.excel_lib_rary.config.Config;
import com.okoj.excel_lib_rary.data.RemoteResp;
import com.okoj.excel_lib_rary.data.entity.WpsCommon;
import com.okoj.excel_lib_rary.data.net.WpsClient;
import com.okoj.excel_lib_rary.listener.LoadDataListener;
import com.okoj.excel_lib_rary.oss.OssDownloadListener;
import com.okoj.excel_lib_rary.oss.OssManager;
import com.okoj.excel_lib_rary.oss.OssUploadListener;
import com.okoj.excel_lib_rary.util.FileUtil;
import com.okoj.excel_lib_rary.util.WpsHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.List;
import java.util.UUID;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.functions.Function2;
import okhttp3.MediaType;
import okhttp3.RequestBody;

import static com.okoj.excel_lib_rary.util.FileUtil.creteFilePath;
import static com.okoj.excel_lib_rary.util.FileUtil.getFileExtName;
import static com.okoj.excel_lib_rary.util.FileUtil.scan;

public class EditActivity extends AppCompatActivity {


    private static final String TAG = EditActivity.class.getSimpleName();

    public static final int NEW_FILE = 0x23;/* 新建文件 */
    public static final int EDIT_LOCAL_FILE = 0x24;/* 编辑本地文件 */
    public static final int EDIT_REMOTE_FILE = 0x25;/* 编辑用户服务端的文件 */
    public static final int PREVIEW_REMOTE_TEMPLATE = 0x26;/* 预览模板 */


    private final static int FILE_CHOOSER_RESULT_CODE = 10000;


    private String fileType;
    private String fileId;

    public int mode = NEW_FILE;
    private String filePath = "";

    private String templateId = "";

    WebView webView;
    public TextView mTvRight;
    ImageView ivBack;

    Config config = WpsClient.getAppConfig();

    private Handler handler = new Handler();

    QMUITipDialog loadingDialog;

    private ValueCallback<Uri> uploadMessage;
    private ValueCallback<Uri[]> uploadMessageAboveL;

    public static void createFile(Context context, String fileType) {
        Intent intent = new Intent(context, EditActivity.class);
        intent.putExtra("fileType", fileType);
        intent.putExtra("mode", NEW_FILE);
        context.startActivity(intent);
    }

    public static void editLocalFile(Context context, String filePath, String fileType) {
        Intent intent = new Intent(context, EditActivity.class);
        intent.putExtra("filePath", filePath);
        intent.putExtra("mode", EDIT_LOCAL_FILE);
        intent.putExtra("fileType", fileType);
        context.startActivity(intent);
    }

    public static void editRemoteFile(Context context, String fileId, String fileType) {
        Intent intent = new Intent(context, EditActivity.class);
        intent.putExtra("fileId", fileId);
        intent.putExtra("mode", EDIT_REMOTE_FILE);
        intent.putExtra("fileType", fileType);
        context.startActivity(intent);
    }

    public static void previewTemplateFile(Context context, String templateId, String fileType) {
        Intent intent = new Intent(context, EditActivity.class);
        intent.putExtra("templateId", templateId);
        intent.putExtra("mode", PREVIEW_REMOTE_TEMPLATE);
        intent.putExtra("fileType", fileType);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.wps_activity_new_excel);
        webView = findViewById(R.id.web_view);
        mTvRight = findViewById(R.id.tv_right);
        ivBack = findViewById(R.id.iv_back);
        initDialog();
        initTopBar();
        getExcelIntentData();
        setMode(mode);
        if (mode == NEW_FILE) {
            inputFileNameDialog();
        } else if (mode == EDIT_LOCAL_FILE) {
            openFile();
        } else if (mode == EDIT_REMOTE_FILE) {
            prepareRemoteFile();
        } else if (mode == PREVIEW_REMOTE_TEMPLATE) {
            // 预览模板

            RemoteResp.previewTemplate(templateId, fileType, new LoadDataListener<WpsCommon>() {
                @Override
                public void onStart() {

                }

                @Override
                public void onSuccess(WpsCommon data) {
                    fileId = data.getId();
                    startWebView(data.getPreview_url());
                }

                @Override
                public void onError(String msg) {
                    Log.e(TAG, "previewTemplate:" + msg);
                }
            });

        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        destoryDialog();
    }


    @Override
    public void onBackPressed() {
        new QMUIDialog.MessageDialogBuilder(this)
                .setTitle("提示")
                .setMessage("确定要退出编辑吗？")
                .addAction("取消", (dialog, index) -> dialog.dismiss())
                .addAction("确定", (dialog, index) -> {
                    dialog.dismiss();
                    super.onBackPressed();
                })
                .show();
    }

    /**
     * 设置模式
     *
     * @param mode
     */
    private void setMode(int mode) {
        this.mode = mode;
        if (mode == PREVIEW_REMOTE_TEMPLATE) {
            mTvRight.setText("编辑");
        } else {
            mTvRight.setText("导出");
        }
    }

    private void inputFileNameDialog() {
        final QMUIDialog.EditTextDialogBuilder builder = new QMUIDialog.EditTextDialogBuilder(this);
        builder.setTitle("今日日记")
                .setPlaceholder("请输入你的日记名称")
                .setInputType(InputType.TYPE_CLASS_TEXT)
                .addAction("取消", (dialog, index) -> {
                    dialog.dismiss();
                    finish();
                })
                .addAction("确定", (dialog, index) -> {
                    CharSequence text = builder.getEditText().getText();
                    if (text != null && text.length() > 0) {
                        newFile(text.toString() + getFileExtName(fileType));
                        dialog.dismiss();
                    } else {
                        Toast.makeText(EditActivity.this, "请输入你的日记名称", Toast.LENGTH_SHORT).show();
                    }
                })
                .setCancelable(false)
                .setCanceledOnTouchOutside(false)
                .show();

    }

    private void newFile(String newFileName) {
        showLoadDialog();
        WpsClient.getInstance().wpsService().newFile(config.getToken(),
                config.getAppid(),
                config.get_w_env(),
                fileType,
                config.get_w_platform(), newFileName)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<JsonObject>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull JsonObject jsonObject) {
                        hideLoadDialog();
                        Log.i(TAG, "onNext:" + jsonObject.toString());
                        try {
                            int code = jsonObject.get("code").getAsInt();
                            if (code == 0) { // 成功
                                String url = jsonObject.getAsJsonObject("data").get("redirect_url").getAsString();
                                fileId = jsonObject.getAsJsonObject("data").get("id").getAsInt() + "";
                                startWebView(url);
                            } else {

                            }


                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        e.printStackTrace();
                        Log.i(TAG, "onError:" + e.toString());
                        hideLoadDialog();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void openFile() {
        uploadFIleToOss();
    }

    private void prepareRemoteFile() {
        showLoadDialog();
        WpsClient.getInstance().wpsService().preview(config.getToken(), fileId, config.getAppid(), config.get_w_env(), fileType, config.get_w_platform())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<JsonObject>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull JsonObject jsonObject) {
                        Log.i(TAG, jsonObject.toString());
                        String previewUrl = jsonObject.get("data").getAsJsonObject().get("preview_url").getAsString();
                        startWebView(previewUrl);
                        hideLoadDialog();
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        e.printStackTrace();
                        Log.e(TAG, e.getMessage());
                        hideLoadDialog();
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

    private void uploadFIleToOss() {
        // 上传文件到oss
        if (TextUtils.isEmpty(filePath)) {
            return;
        }
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            return;
        }

        String extName = FileUtil.getExtName(targetFile.getName());
        String uploadFileName = UUID.randomUUID().toString().replace("-", "") + extName;

        showLoadDialog();

        OssManager.getInstance().updateWpsFileToIjjStatic(targetFile.getAbsolutePath(),
                uploadFileName,
                config.getAppid(),
                config.getEnvString(),
                config.getUserId(), new OssUploadListener() {
                    @Override
                    public void progress(int progress) {
                        Log.i(TAG, "OssUploadProgress:" + progress);
                    }

                    @Override
                    public void success(PutObjectRequest request, PutObjectResult result) {
                        Log.i(TAG, "OssUploadSuccess:" + request.toString());
                        uploadInfoToServer(request.getObjectKey(), targetFile.getName());
                        handler.post(() -> {
                            hideLoadDialog();
                        });
                    }

                    @Override
                    public void success(List<String> pathList) {
                        Log.i(TAG, "OssUploadPathList:" + pathList.size());
                    }

                    @Override
                    public void failure() {
                        Log.e(TAG, "OssUploadFailure:");
                        handler.post(() -> {
                            hideLoadDialog();
                        });
                    }
                });


    }

    private void uploadInfoToServer(String downloadUrl, String name) {

        String body = "";
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("download_url", downloadUrl);
            jsonObject.put("name", name);
            jsonObject.put("_w_app_id", config.getAppid());
            jsonObject.put("_w_env", config.get_w_env());
            jsonObject.put("_w_platform", config.get_w_platform());
            jsonObject.put("file_type", fileType);
            body = jsonObject.toString();
            Log.d(TAG, body);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);

        WpsClient.getInstance().wpsService()
                .upload(config.getToken(), requestBody)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<JsonObject>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                    }

                    @Override
                    public void onNext(@NonNull JsonObject jsonObject) {
                        Log.i(TAG, "onNext" + jsonObject.toString());

                        try {
                            String previewUrl = jsonObject.get("data").getAsJsonObject().get("preview_url").getAsString();
                            fileId = jsonObject.get("data").getAsJsonObject().get("id").getAsString();
                            startWebView(previewUrl);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        e.printStackTrace();
                        Log.e(TAG, "onError" + e.toString());
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

    private void getExcelIntentData() {
        fileType = getIntent().getStringExtra("fileType");
        mode = getIntent().getIntExtra("mode", NEW_FILE);
        filePath = getIntent().getStringExtra("filePath");
        fileId = getIntent().getStringExtra("fileId");
        templateId = getIntent().getStringExtra("templateId");
    }

    private void startWebView(String url) {
        WebSettings settings = webView.getSettings();
        settings.setDomStorageEnabled(true);
        settings.setDatabaseEnabled(true);
        settings.setJavaScriptEnabled(true);
        settings.setBlockNetworkImage(false);

        settings.setJavaScriptCanOpenWindowsAutomatically(true);//支持通过JS打开新窗口
        settings.setAllowFileAccess(true);                      //设置可以访问文件
        settings.setSupportZoom(true);                          //支持缩放
        settings.setBuiltInZoomControls(true);                  //设置内置的缩放控件
        settings.setUseWideViewPort(true);                      //自适应屏幕
        settings.setSupportMultipleWindows(true);               //多窗口
        settings.setDefaultTextEncodingName("utf-8");            //设置编码格式
        settings.setAppCacheEnabled(true);
        settings.setDomStorageEnabled(true);
        settings.setAppCacheMaxSize(Long.MAX_VALUE);
        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);       //缓存模式

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                String tokenJSMethod = String.format("javascript:function WPS_GetToken(){return {token : '%s'} }", config.getToken());
                view.loadUrl(tokenJSMethod);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
            }

            @Override
            public void onLoadResource(WebView view, String url) {
                super.onLoadResource(view, url);
            }


        });
        webView.setWebChromeClient(new WebChromeClient() {
                                       @Override
                                       public void onProgressChanged(WebView view, int newProgress) {
                                           super.onProgressChanged(view, newProgress);
                                           String tokenJSMethod = String.format("javascript:function WPS_GetToken(){return {token : '%s'} }", config.getToken());
                                           Log.i(TAG, tokenJSMethod);
                                           view.loadUrl(tokenJSMethod);
                                       }


                                       //For Android  >= 4.1
                                       public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                                           uploadMessage = null;
                                           uploadMessageAboveL = null;
                                           uploadMessage = valueCallback;
                                           openImageChooserActivity();
                                       }

                                       // For Android >= 5.0
                                       @Override
                                       public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                                           uploadMessage = null;
                                           uploadMessageAboveL = null;
                                           uploadMessageAboveL = filePathCallback;
                                           openImageChooserActivity();
                                           return true;
                                       }

                                   }


        );
        webView.loadUrl(url);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_RESULT_CODE && data != null && resultCode == RESULT_OK) { //处理返回的图片，并进行上传
            if (null == uploadMessage && null == uploadMessageAboveL) return;
            Uri result = data.getData();
            handleCompress(result);
        }
    }


    private void handleCompress(Uri result) {
        LogUtils.d("选择本地图片的Uri" + result);
        Luban.Companion.with(this)
                .load(result)
                .ignoreBy(200)
                .quality(95)
                .compressObserver(new Function1<CompressResult<Uri, File>, Unit>() {
                    @Override
                    public Unit invoke(CompressResult<Uri, File> uriFileCompressResult) {
                        uriFileCompressResult.setOnSuccess(new Function1<File, Unit>() {
                            @Override
                            public Unit invoke(File file) {
                                hideLoadDialog();
                                LogUtils.d("压缩成功" + file.getAbsolutePath());
                                Uri uriForFile = BaseConfigFileProvider.getUriForFile(EditActivity.this, AppUtils.getAppPackageName() + ".fileProvider", file);
                                if (null != uploadMessageAboveL) {
                                    Uri[] results = new Uri[]{uriForFile};
                                    uploadMessageAboveL.onReceiveValue(results);
                                } else {
                                    uploadMessage.onReceiveValue(uriForFile);
                                }
                                return Unit.INSTANCE;
                            }
                        });

                        uriFileCompressResult.setOnError(new Function2<Throwable, Uri, Unit>() {
                            @Override
                            public Unit invoke(Throwable throwable, Uri uri) {
                                hideLoadDialog();
                                LogUtils.d("压缩失败" + throwable.getMessage() + "--" + uri);
                                if (null != uploadMessageAboveL) {
                                    Uri[] results = new Uri[]{result};
                                    uploadMessageAboveL.onReceiveValue(results);
                                }else {
                                    uploadMessage.onReceiveValue(result);
                                }
                                return Unit.INSTANCE;
                            }
                        });

                        uriFileCompressResult.setOnCompletion(new Function0<Unit>() {
                            @Override
                            public Unit invoke() {
                                LogUtils.d("压缩结束");
                                hideLoadDialog();
                                return Unit.INSTANCE;
                            }
                        });

                        uriFileCompressResult.setOnStart(new Function0<Unit>() {
                            @Override
                            public Unit invoke() {
                                LogUtils.d("压缩开始");
                                showLoadDialog();
                                return Unit.INSTANCE;
                            }
                        });

                        return Unit.INSTANCE;
                    }

                }).launch();
    }

    /**
     * 不处理图片压缩
     *
     * @param requestCode
     * @param resultCode
     * @param intent
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
        if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
            return;
        Uri[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (intent != null) {
                String dataString = intent.getDataString();
                ClipData clipData = intent.getClipData();
                if (clipData != null) {
                    results = new Uri[clipData.getItemCount()];
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        ClipData.Item item = clipData.getItemAt(i);
                        results[i] = item.getUri();
                    }
                }
                if (dataString != null)
                    results = new Uri[]{Uri.parse(dataString)};
            }
        }
        uploadMessageAboveL.onReceiveValue(results);
        uploadMessageAboveL = null;
    }


    private void downloadCurrentFile() {
        if (TextUtils.isEmpty(fileId)) {
            showTipDialog("获取文件id异常，保存失败", 2000);
            return;
        }
        showLoadDialog();
        WpsClient.getInstance()
                .wpsService()
                .getNewFile(config.getToken(), fileId, config.getAppid(), config.get_w_env(), config.get_w_platform())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .map(result -> result.getData())
                .flatMap(remoteFile -> Observable.create(emitter -> {
                    File file = creteFilePath(remoteFile.getName(), remoteFile.getDownload_url());
                    OssManager.getInstance().downloadWps(file.getAbsolutePath(), remoteFile.getDownload_url(), new OssDownloadListener() {
                        @Override
                        public void success(String filePath) {
                            Log.d(TAG, "上传成功: " + filePath);
                            scan(filePath, EditActivity.this);
                            emitter.onNext(file);
                        }

                        @Override
                        public void failure(String message) {
                            Log.d(TAG, "上传失败: " + message);
                            emitter.onError(new Exception("上传异常"));
                        }
                    });
                }))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Object>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Object o) {
                        Log.d(TAG, "导出本地成功: " + o);
                        hideLoadDialog();
                        showTipDialog("导出本地成功", 2000);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        Log.d(TAG, "导出本地失败: " + e.getMessage());
                        showTipDialog("导出本地失败", 2000);
                        hideLoadDialog();
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }

    private void initDialog() {
        loadingDialog = new QMUITipDialog.Builder(this)
                .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
                .setTipWord("正在加载")
                .create();
    }

    private void destoryDialog() {
        loadingDialog.cancel();
        loadingDialog = null;
    }

    private void showLoadDialog() {
        loadingDialog.show();
    }

    /**
     * @param msg 信息提示
     * @param sec 保留时间
     */
    private void showTipDialog(String msg, long sec) {
        QMUITipDialog tipDialog = new QMUITipDialog.Builder(this)
                .setTipWord(msg)
                .create();
        tipDialog.show();
        handler.postDelayed(tipDialog::dismiss, sec);
    }

    private void hideLoadDialog() {
        loadingDialog.dismiss();
    }


    private void initTopBar() {
        mTvRight.setOnClickListener(v -> {
            if (mode == PREVIEW_REMOTE_TEMPLATE) {
                // 编辑模板
                editTemplate();
            } else {
                outPort();
            }
        });
        ivBack.setOnClickListener(v -> {
            onBackPressed();
        });
    }

    public void editTemplate() {
        RemoteResp.editPublicTemplate(fileId, fileType, new LoadDataListener<WpsCommon>() {
            @Override
            public void onStart() {

            }

            @Override
            public void onSuccess(WpsCommon data) {
                fileId = data.getId();
                startWebView(data.getPreview_url());
                setMode(EDIT_REMOTE_FILE);
            }

            @Override
            public void onError(String msg) {

            }
        });
    }

    public void outPort() {
        boolean canImport = true;
        if (WpsHelper.getBizCallBack() != null) {
            canImport = WpsHelper.getBizCallBack().canImportFile();
        }
        if (!canImport) {
            return;
        }
        showDownloadTipDialog();
    }

    private void showDownloadTipDialog() {
        QMUIDialog show = new QMUIDialog.MessageDialogBuilder(this)
                .setTitle("提示")
                .setMessage("为确保您保存为最新版本，请先点击页面右上角“设置”按钮中的“保存版本”，再进行导出")
                .addAction("取消", (dialog, index) -> dialog.dismiss())
                .addAction("确定", (dialog, index) -> {
                    dialog.dismiss();
                    downloadCurrentFile();
                })
                .show();
    }


    private void openImageChooserActivity() {

        //调用自己的图库
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);
    }

}
